# coding = utf-8

import tkinter
from tkinter import messagebox
from tkinter import ttk

from map_artist.attribute_def import (ROAD_AREA_VALUE,
                                      APPENDIX_ATTRIBUTE_VALUE)


class ParaWidget:
    def __init__(self, master):
        self.master = master
        self.widgettype = None

    def destroyChildren(self, title):
        if self.master.winfo_children():
            for child in self.master.winfo_children():
                if child['text'] == title:
                    child.destroy()

    def destroyWidgetInChildren(self, title):
        if self.master.winfo_children():
            for child in self.master.winfo_children():
                print('child is ', child['text'])
                if child['text'] == title:
                    print('destroy in', title)
                    for widget in child.winfo_children():
                        print('destroy a widget in', title)
                        widget.destroy()

    def destroy(self):
        for child in self.master.winfo_children():
            child.destroy()

    def updateValue(self):
        pass


class EmptyWidget(ParaWidget):
    """
    空类型界面.继承自ParaWidget类,主要功能:
    1.实例化1个LabelFrame,显示:无目标
    """
    def __init__(self, master):
        super().__init__(master)
        self.widgettype = 'empty'
        tkinter.Label(self.master, text='未选中任何目标', width=42).grid(column=0,
                                                                  row=0)


class AppendixParaWidget(ParaWidget):
    """
    附属物属性参考界面.继承自ParaWidget类,主要功能:
    1.实例化4个LabelFrame,来分别显示:类型/属性/归属/按键 4个界面
    """
    def __init__(self, master, event_trigger):
        super().__init__(master)
        self.widgettype = 'appendix'
        self.event_trigger = event_trigger
        type_frame = tkinter.LabelFrame(master, text='type', width=30)
        attribute_frame = tkinter.LabelFrame(master,
                                             text='attribute',
                                             width=30)
        belong_frame = tkinter.LabelFrame(master, text='belong', width=30)
        button_frame = tkinter.LabelFrame(master, width=30)

        type_frame.grid(column=0, row=0, sticky=tkinter.W)
        self.area_type = tkinter.StringVar()
        self.initTypeFrame(type_frame)

        belong_frame.grid(column=0, row=1, sticky=tkinter.W)
        self.initBelongFrame(belong_frame)

        attribute_frame.grid(column=0, row=2, sticky=tkinter.W)
        self.attribute_frame = attribute_frame
        self.initAttributeFrame(attribute_frame)

        button_frame.grid(column=0, row=3, sticky=tkinter.W)
        self.initButtonFrame(button_frame)

    def updateValue(self, key=0, value=0):
        pass

    def initTypeFrame(self, master):
        row1 = tkinter.Frame(master)
        row1.pack(fill="x")
        tkinter.Label(row1, text='附属物ID：', width=12).pack(side=tkinter.LEFT)
        self.id_value = tkinter.StringVar()
        tkinter.Label(row1,
                      textvariable=self.id_value,
                      width=4 * 8,
                      anchor='w').pack(side=tkinter.LEFT)
        #
        # row2 = tkinter.Frame(self)
        # row2.pack(fill="x")
        # tkinter.Label(row2, text='附属物ID：', width=12).pack(side=tkinter.LEFT)
        # tkinter.Label(row2, text='{}'.format(ref_line_id), width=6).pack(side=tkinter.LEFT)
        #
        row_area_type = tkinter.Frame(master)
        row_area_type.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row_area_type, text='附属物属性',
                      width=12).pack(side=tkinter.LEFT)
        box_area_type = ttk.Combobox(row_area_type,
                                     textvariable=self.area_type,
                                     width=12)
        box_area_type.pack(side=tkinter.LEFT, padx=6)
        box_area_type['value'] = APPENDIX_ATTRIBUTE_VALUE
        box_area_type.current(1)
        self.box_area_type = box_area_type
        pass

    def initAttributeFrame(self, master):
        row = tkinter.Frame(master)
        row.pack(side=tkinter.TOP)
        tkinter.Label(row, text='附属物位置', width=12).pack(side=tkinter.LEFT)
        self.position_list = tkinter.StringVar()
        self.position_list.set('{}'.format([0.0, 0.0]))
        tkinter.Entry(row,
                      textvariable=self.position_list,
                      state='readonly',
                      width=4 * 8).pack(side=tkinter.LEFT)
        pass

    def updateAttributeFrame(self, id_list, position_list):
        if self.attribute_frame.winfo_children():
            for child in self.attribute_frame.winfo_children():
                child.destroy()
        for i, center in enumerate(position_list):
            row = tkinter.Frame(self.attribute_frame)
            row.grid(column=0, row=i)
            tkinter.Label(row, text='附属物{}位置'.format(id_list[i]),
                          width=12).grid(column=0, row=0)
            tkinter.Label(row,
                          text='{:.2f}, {:.2f}'.format(center[0], center[1]),
                          width=4 * 8).grid(column=1, row=0)

    def initBelongFrame(self, master):
        tkinter.Label(master, text='所属车道ID', width=12).pack(side=tkinter.LEFT)
        self.belongs_id_list = tkinter.StringVar()
        self.belongs_id_list.set('0')
        tkinter.Entry(master,
                      textvariable=self.belongs_id_list,
                      state='readonly',
                      width=4 * 8).pack(side=tkinter.LEFT)
        pass

    def initButtonFrame(self, master):
        tkinter.Button(master, text='OK',
                       command=self.onOK).grid(column=0,
                                               row=0,
                                               sticky=tkinter.E)
        pass

    def onOK(self):
        self.event_trigger.get()
        pass


class RefLineParaWidget(ParaWidget):
    """
    参考线属性参考界面.继承自ParaWidget类,主要功能:
    1.实例化4个LabelFrame,来分别显示:配置/起始点/车道线/按键 4个界面
    """
    def __init__(self, master, event_trigger):  # artist : MapLine类或者MapPolygon
        super().__init__(master)
        self.widgettype = 'ref'
        self.event_trigger = event_trigger
        # 生成4个frame
        configuration_frame = tkinter.LabelFrame(master,
                                                 text='configuration',
                                                 width=40)
        endpoint_display_frame = tkinter.LabelFrame(master,
                                                    text='endpoint',
                                                    width=40)
        board_line_display_frame = tkinter.LabelFrame(master,
                                                      text='board',
                                                      width=40)
        button_display_frame = tkinter.LabelFrame(master, width=40)

        # 放置frame,并初始化
        configuration_frame.grid(column=0, row=0, sticky=tkinter.W)
        configuration_frame.grid_propagate(0)
        self.initConfigurationFrame(configuration_frame)

        endpoint_display_frame.grid(column=0, row=1, sticky=tkinter.W)
        endpoint_display_frame.grid_propagate(0)
        self.initEndpointDislplayFrame(endpoint_display_frame)

        board_line_display_frame.grid(column=0, row=2, sticky=tkinter.W)
        # board_line_display_frame.grid_propagate(0)
        self.board_line_display_frame = board_line_display_frame
        self.initBoardDisplayFrame(board_line_display_frame)

        button_display_frame.grid(column=0, row=3, sticky=tkinter.S)
        # button_display_frame.grid_propagate(0)
        self.initButtonFrame(button_display_frame)
        pass

    def setupRow(self, row, text, var):
        row.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row, text=text, width=12).pack(side=tkinter.LEFT)
        entry_id = tkinter.Entry(row, textvariable=var, width=12)
        entry_id.pack(side=tkinter.LEFT, padx=6)
        return entry_id

    def setupComboRow(self, row, text, var, value_list):
        pass
        row.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row, text=text, width=12).pack(side=tkinter.LEFT)
        box = ttk.Combobox(row, textvariable=var,
                           width=12).pack(side=tkinter.LEFT, padx=6)
        box['value'] = value_list

    def initConfigurationFrame(self, config_frame):
        """
        style_list.append('{}'.format(int(self.index)))
        style_list.append('{}'.format(self.speed_limited[0]))
        style_list.append('{}'.format(self.speed_limited[1]))
        style_list.append('{}'.format(self.height_limited))
        style_list.append('{}'.format(self.curvature))
        style_list.append('{}'.format(int(self.lanes_number)))
        style_list.append('{}'.format(self.ratio))
        style_list.append('{}'.format(int(self.direction)))
        style_list.append('{}'.format(self.slength))
        style_list.append('{}'.format(self.start[0]))
        style_list.append('{}'.format(self.start[1]))
        style_list.append('{}'.format(0.0))  # (self.startpoint[2]))
        style_list.append('{}'.format(self.end[0]))
        style_list.append('{}'.format(self.end[1]))
        style_list.append('{}'.format(0.0))  # (self.endpoint[2]))
        style_list.append('{}'.format(int(self.material)))
        style_list.append('{}'.format(int(self.area)))
        """
        self.current_line_id = tkinter.StringVar()
        self.speed_lower = tkinter.StringVar()
        self.speed_upper = tkinter.StringVar()
        self.height_limited = tkinter.StringVar()
        self.lanes_number = tkinter.StringVar()
        # self.road_material = tkinter.StringVar()
        # self.area_type = tkinter.StringVar()
        self.ratio = tkinter.StringVar()
        row1 = tkinter.Frame(config_frame)
        row1.pack(fill="x")
        tkinter.Label(row1, text='参考线ID：', width=12).pack(side=tkinter.LEFT)
        self.name = tkinter.StringVar()
        tkinter.Label(row1, textvariable=self.current_line_id,
                      width=12).pack(side=tkinter.LEFT)
        # 第二行
        row2 = tkinter.Frame(config_frame)
        self.speed_lower.set(1)
        self.setupRow(row2, '车速下限：', self.speed_lower)
        tkinter.Label(row2, text='m/s', width=12).pack(side=tkinter.LEFT)
        # 第三行
        row3 = tkinter.Frame(config_frame)
        self.speed_upper.set(10)
        self.setupRow(row3, '车速上限：', self.speed_upper)
        tkinter.Label(row3, text='m/s', width=12).pack(side=tkinter.LEFT)
        #
        row_height = tkinter.Frame(config_frame)
        self.height_limited.set(20)
        self.setupRow(row_height, '高度限制：', self.height_limited)
        tkinter.Label(row_height, text='m', width=12).pack(side=tkinter.LEFT)
        #
        row_curv = tkinter.Frame(config_frame)
        row_curv.pack(fill="x")
        tkinter.Label(row_curv, text='曲率(1/m)：',
                      width=12).pack(side=tkinter.LEFT)
        self.curvature = tkinter.StringVar()
        self.curvature.set(0.0)
        tkinter.Label(row_curv, textvariable=self.curvature,
                      width=12).pack(side=tkinter.LEFT)
        # 第四行
        row4 = tkinter.Frame(config_frame)
        self.lanes_number.set(1)
        self.lanes_number_entry = self.setupRow(row4, '车道数量：',
                                                self.lanes_number)
        self.lanes_number.trace_variable("w", self.updateBoardDisplayFrame)
        #
        row_ratio = tkinter.Frame(config_frame)
        self.ratio.set(0)
        self.setupRow(row_ratio, '道路坡度：', self.ratio)
        # 第五行
        row5 = tkinter.Frame(config_frame)
        row5.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row5, text='行车方向', width=12).pack(side=tkinter.LEFT)

        row_straight = tkinter.Frame(row5)
        row_straight.pack(side=tkinter.LEFT)
        row_turn = tkinter.Frame(row5)
        row_turn.pack(side=tkinter.LEFT)
        row_trend = tkinter.Frame(row5)
        row_trend.pack(side=tkinter.LEFT)
        row_bid = tkinter.Frame(row5)
        row_bid.pack(side=tkinter.LEFT)

        # checkbutton0
        self.straight_value = tkinter.IntVar()
        self.straight_ck = tkinter.Checkbutton(row_straight,
                                               text='直行',
                                               variable=self.straight_value)
        self.straight_ck.deselect()
        self.straight_ck.pack(side=tkinter.TOP)
        # checkbutton1
        self.left_turn_value = tkinter.IntVar()
        self.left_turn_ck = tkinter.Checkbutton(row_turn,
                                                text='左转',
                                                variable=self.left_turn_value)
        self.left_turn_ck.pack(side=tkinter.TOP)

        self.right_turn_value = tkinter.IntVar()
        self.right_turn_ck = tkinter.Checkbutton(
            row_turn, text='右转', variable=self.right_turn_value)
        self.right_turn_ck.pack(side=tkinter.TOP)
        # checkbutton2
        self.left_trend_value = tkinter.IntVar()
        self.left_trend_ck = tkinter.Checkbutton(
            row_trend, text='左斜', variable=self.left_trend_value)
        self.left_trend_ck.pack(side=tkinter.TOP)

        self.right_trend_value = tkinter.IntVar()
        self.right_trend_ck = tkinter.Checkbutton(
            row_trend, text='右斜', variable=self.right_trend_value)
        self.right_trend_ck.pack(side=tkinter.TOP)
        # checkbutton3
        self.bidirect_value = tkinter.IntVar()
        self.bidirect_ck = tkinter.Checkbutton(row_bid,
                                               text='双向',
                                               variable=self.bidirect_value)
        self.bidirect_ck.pack(side=tkinter.TOP)
        # 第六行
        row6 = tkinter.Frame(config_frame)
        row6.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row6, text='道路材料', width=12).pack(side=tkinter.LEFT)
        material_box = ttk.Combobox(row6, width=12)
        material_box.pack(side=tkinter.LEFT, padx=6)
        material_box['value'] = ['未知', '沥青', '水泥']
        material_box.current(1)
        self.material_box = material_box
        # 第七行
        row_area_type = tkinter.Frame(config_frame)
        row_area_type.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row_area_type, text='区域属性',
                      width=12).pack(side=tkinter.LEFT)
        box_area_type = ttk.Combobox(row_area_type, width=12)
        box_area_type.pack(side=tkinter.LEFT, padx=6)
        box_area_type['value'] = ROAD_AREA_VALUE
        box_area_type.current(1)
        self.box_area_type = box_area_type
        pass

    def setDirection(self, direction):
        self.straight_value.set((direction & 1 << 0) >> 0)
        if self.straight_value.get() != 0:
            self.straight_ck.select()
        else:
            self.straight_ck.deselect()

        self.left_turn_value.set((direction & 1 << 1) >> 1)
        if self.left_turn_value.get() != 0:
            self.left_turn_ck.select()
        else:
            self.left_turn_ck.deselect()

        self.right_turn_value.set((direction & 1 << 2) >> 2)
        if self.right_turn_value.get() != 0:
            self.right_turn_ck.select()
        else:
            self.right_turn_ck.deselect()

        self.left_trend_value.set((direction & 1 << 3) >> 3)
        if self.left_trend_value.get() != 0:
            self.left_trend_ck.select()
        else:
            self.left_trend_ck.deselect()

        self.right_trend_value.set((direction & 1 << 4) >> 4)
        if self.right_trend_value.get() != 0:
            self.right_trend_ck.select()
        else:
            self.right_trend_ck.deselect()

        self.bidirect_value.set((direction & 1 << 5) >> 5)
        if self.bidirect_value.get() != 0:
            self.bidirect_ck.select()
        else:
            self.bidirect_ck.deselect()

    def getDirection(self):
        traffic_direct_value = [
            self.straight_value.get(),
            self.left_turn_value.get(),
            self.right_turn_value.get(),
            self.left_trend_value.get(),
            self.right_trend_value.get(),
            self.bidirect_value.get()
        ]
        direction = 0
        for i, value in enumerate(traffic_direct_value):  #
            direction += int(value) << i
        return direction

    def updateEndpointsValue(self, start_point, end_point):
        value = ', '.join(list('{:.2f}'.format(data) for data in start_point))
        self.start_point.set(value)
        value = ', '.join(list('{:.2f}'.format(data) for data in end_point))
        self.end_point.set(value)

    def initEndpointDislplayFrame(self, endpoint_frame):
        start_point_frame = tkinter.Frame(endpoint_frame)
        start_point_frame.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(start_point_frame, text='起点坐标',
                      width=12).pack(side=tkinter.LEFT)
        self.start_point = tkinter.StringVar()
        value = ','.join(list('{:.2f}'.format(data) for data in (0.0, 0.0)))
        self.start_point.set(value)
        tkinter.Label(start_point_frame,
                      textvariable=self.start_point,
                      width=18).pack(side=tkinter.LEFT)

        end_point_frame = tkinter.Frame(endpoint_frame)
        end_point_frame.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(end_point_frame, text='终点坐标',
                      width=12).pack(side=tkinter.LEFT)
        self.end_point = tkinter.StringVar()
        value = ','.join(list('{:.2f}'.format(data) for data in (0.0, 0.0)))
        self.end_point.set(value)
        tkinter.Label(end_point_frame, textvariable=self.end_point,
                      width=18).pack(side=tkinter.LEFT)
        pass

    def updateBoardDisplayFrame(self, *args):
        print('get', self.lanes_number.get())
        # if self.lanes_number.get() and int(self.lanes_number.get()) > 0:
        #     # print('destroy old')
        #     self.destroyWidgetInChildren('board')
        #     # print('create new')
        #     self.initBoardDisplayFrame(self.board_line_display_frame)

    def updateBoardsValue(self, boards_value):
        """
        boards_value : list(int)
        """
        print('boards_value is', boards_value)
        value = '-'.join(list(str(data) for data in boards_value))
        print('value = ', value)
        self.boards_value.set(value)
        pass

    def initBoardDisplayFrame(self, board_frame):
        """
        Label : Entry(readonly)
        """
        frame_i = tkinter.Frame(board_frame)
        frame_i.grid(column=0, row=0, sticky=tkinter.W)
        tkinter.Label(frame_i, text='边界序列', width=12).pack(side=tkinter.LEFT)
        self.boards_value = tkinter.StringVar()
        # self.boards_value.set(i)
        board_entry = tkinter.Entry(frame_i, width=18)
        board_entry.pack(side=tkinter.LEFT)
        # board_entry.bind('<FocusIn>', self.board_entry_focus_handler)
        board_entry['textvariable'] = self.boards_value
        board_entry['state'] = 'readonly'
        pass

    # def board_entry_focus_handler(self, event):
    #     self.board_widget = event.widget
    #     board_text = self.board_entries_dict[self.board_widget]
    #     if board_text:
    #         board_text.set('demo, todo')
    #     else:
    #         board_text.set('plz select a board line to show')

    def initButtonFrame(self, button_frame):
        tkinter.Button(button_frame, text='OK',
                       command=self.onOK).grid(column=0,
                                               row=0,
                                               sticky=tkinter.E)
        pass

    def onOK(self):
        # self.artist.speed_limited[0] = self.speed_lower.get()
        # self.artist.speed_limited[1] = self.speed_upper.get()
        # self.artist.height_limited = self.height_limited.get()
        # self.artist.lanes_number = int(self.lanes_number.get())
        # self.artist.ratio = self.ratio.get()
        # traffic_direct_value = [
        #     self.straight_value.get(),
        #     self.left_turn_value.get(),
        #     self.right_trend_value.get(),
        #     self.bidirect_value.get()
        # ]
        # direction = 0
        # for i, value in enumerate(traffic_direct_value):  #
        #     direction += 2**(i) * int(value)
        # self.artist.direction = direction
        # self.artist.road_material = self.material_box['value'].index(
        #     self.material_box.get())
        # self.artist.area = self.box_area_type['value'].index(
        #     self.box_area_type.get())
        self.event_trigger.get()
        pass

    def updateValue(self, key=0, value=0):
        pass


class BoardLineParaWidget(ParaWidget):
    def __init__(self, master, event_trigger):  # artist : MapLine类或者MapPolygon
        super().__init__(master)
        self.widgettype = 'board'
        self.event_trigger = event_trigger
